package com.df.excel_export.utils;

import com.df.excel_export.common.ClassDefine;
import com.df.excel_export.common.Constant;
import com.df.excel_export.common.EnumDefine;
import com.df.excel_export.validator.IFieldValidator;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Slf4j
public class ValidatorUtils {

    public static void parserValidateRule(boolean isListCheck, ClassDefine nowClassDefine, String validateRule, List<IFieldValidator> validators, String fileName, String sheetName, int i, int nowRow) {


        parserDefaultValidator(nowClassDefine,validateRule,validators,fileName,sheetName,i,nowRow);
        if(!validators.isEmpty()){
            return;
        }
        parserLenValidator(nowClassDefine,validateRule,validators,fileName,sheetName,i,nowRow);
        if(!validators.isEmpty()){
            return;
        }
        parserEnumValidator(nowClassDefine,validateRule,validators,fileName,sheetName,i,nowRow);
        if(!validators.isEmpty()){
            return;
        }
        ValidatorUtils.parserRangeValidator(nowClassDefine,validateRule,validators,fileName,sheetName,i,nowRow);
        if(!validators.isEmpty()){
            return;
        }
        ValidatorUtils.parserIdValidator(nowClassDefine,validateRule,validators,fileName,sheetName,i,nowRow);
        if(!validators.isEmpty()){
            return;
        }
        if(!isListCheck){
            ValidatorUtils.parserListValidator(nowClassDefine,validateRule,validators,fileName,sheetName,i,nowRow);
            if(!validators.isEmpty()){
                return;
            }
            ValidatorUtils.parserDbListValidator(nowClassDefine,validateRule,validators,fileName,sheetName,i,nowRow);
            if(!validators.isEmpty()){
                return;
            }
        }

        //TODO 使用脚本进行规则解析
        //TODO 如果也没有脚本处理，则打印warning
//        log.warn("未解析的校验串："+validateRule+"，文件名："+fileName+"，sheet名："+sheetName+"，列数："+i+" 当前行："+nowRow);
    }

    private static void parserDbListValidator(ClassDefine nowClassDefine, String validateRule, List<IFieldValidator> validators, String fileName, String sheetName, int i, int nowRow) {
        if(!validateRule.startsWith(Constant.ValidateMark.MARK_DbListStart)){
            return;
        }
        int endIndex = validateRule.indexOf(Constant.ValidateMark.MARK_DbListEnd);
        String indexStr = validateRule.substring(1, endIndex);
        if(indexStr.contains(Constant.ValidateMark.MARK_IndexSeperator)){//限制二位数组项
            String[] split = indexStr.split(Constant.ValidateMark.MARK_IndexSeperator);
            String oneIndexStr = split[0];
            String twoIndexStr = split[1];
            int oneIndex;
            if(oneIndexStr.equals(Constant.ValidateMark.MARK_Any)){
                oneIndex = -1;
            }else {
                oneIndex = Integer.parseInt(oneIndexStr);
            }
            Set<Integer> twoIndexs = new HashSet<>();;
            if(twoIndexStr.contains(Constant.ValidateMark.MARK_And)){
                String[] twoIndexStrs = twoIndexStr.split(Constant.ValidateMark.MARK_And);
                for (String str : twoIndexStrs) {
                    str = str.trim();
                    if(str.contains(Constant.ValidateMark.MARK_IndexRange)){
                        if(!addRangeIndex(str,twoIndexs,fileName,sheetName,i,nowRow)){
                            return;
                        }
                    }else if(str.matches(Constant.CommonRegex.REGEX_Number)){
                        twoIndexs.add(Integer.parseInt(str));
                    }else{
                        log.error("二维列表规则串中二维索引不正确,文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
                        return;
                    }
                }
            }else{
                if(twoIndexStr.contains(Constant.ValidateMark.MARK_IndexRange)){
                    if(!addRangeIndex(twoIndexStr,twoIndexs,fileName,sheetName,i,nowRow)){
                        return;
                    }
                }else{
                    if(twoIndexStr.matches(Constant.CommonRegex.REGEX_Number)){
                        twoIndexs.add(Integer.parseInt(twoIndexStr));
                    }else{
                        log.error("二维列表规则串中二维索引不正确,文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
                        return;
                    }
                }

            }
            String validateStr = validateRule.substring(endIndex + 1);
            List<IFieldValidator> result = new ArrayList<>();
            parserValidateRule(true, nowClassDefine, validateStr,result,fileName,sheetName,i,nowRow);
            if(result.isEmpty()){
                return;
            }
//            DbListValidator validator = new DbListValidator();
//            validator.oneIndex = oneIndex;
//            validator.isLimitOne = false;
//            validator.twoIndex.addAll(twoIndexs);
//            validator.validator = result.get(0);
//            validators.add(validator);
            return;
        }
        int oneIndex =0;
        //限制一维
        if(indexStr.equals(Constant.ValidateMark.MARK_Any)){//对所有一维项满足
            oneIndex = -1;
        }else {
            if(!indexStr.matches(Constant.CommonRegex.REGEX_Number)){
                log.error("二位列表规则串中一维索引不正确,文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
                return;
            }
            oneIndex = Integer.parseInt(indexStr);
        }
        String validateStr = validateRule.substring(endIndex);
        List<IFieldValidator> result = new ArrayList<>();
        parserValidateRule(true, nowClassDefine, validateStr,result,fileName,sheetName,i,nowRow);
        if(result.isEmpty()){
            return;
        }
//        DbListValidatorI validator = new DbListValidatorI();
//        validator.isLimitOne = true;
//        validator.oneIndex = oneIndex;
//        validator.validator = result.get(0);
//        validators.add(validator);
    }

    private static boolean addRangeIndex(String str, Set<Integer> indexContainer, String fileName, String sheetName, int i, int nowRow) {
        String[] range = str.split(Constant.ValidateMark.MARK_IndexRange);
        String minStr = range[0];
        String maxStr = range[1];
        int min = 0;
        if(minStr.matches(Constant.CommonRegex.REGEX_Number)){
            min = Integer.parseInt(minStr);
        }
        int max = 0;
        if(maxStr.matches(Constant.CommonRegex.REGEX_Number)){
            max = Integer.parseInt(maxStr);
        }
        if(min>max){
            log.error("二维列表规则串中二维索引范围书写不正确，应该为 min-max,文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+str);
            return false;
        }
        for (int j = min; j <= max; j++) {
            indexContainer.add(j);
        }
        return true;
    }

    //长度解析
    public static void parserLenValidator(ClassDefine nowClassDefine, String validateRule, List<IFieldValidator> validators, String fileName, String sheetName, int i, int nowRow) {
        if(!validateRule.startsWith(Constant.ValidateMark.MARK_LenStart)){
            return ;
        }
        String tempValue = validateRule.substring(Constant.ValidateMark.MARK_LenStart.length(),validateRule.length()-1);
        String[] split = tempValue.split(Constant.ValidateMark.MARK_IndexSeperator);
        if(split.length!=2){
            log.error("len校验规则格式错误,至少有最小值和最大值,文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
            return ;
        }
        try {
            String minStr = split[0];
            String maxStr = split[1];
            if(minStr.equals(Constant.ValidateMark.MARK_Any)){
                minStr = "0";
            }
            if(maxStr.equals(Constant.ValidateMark.MARK_Any)){
                maxStr = Integer.MAX_VALUE+"";
            }
            int min = Integer.parseInt(minStr);
            min = Math.max(min, 0);//长度最小值不能小于0
            int max = Integer.parseInt(maxStr);
//            LenValidatorI validator = new LenValidatorI();
//            validator.max = min;
//            validator.min = max;
//            validators.add(validator);
            return ;
        }catch (Exception e){
            log.error("len校验规则格式错误,最小值或最大值解析错误,文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
            e.printStackTrace();
            return ;
        }
    }

    //默认值解析
    public static void parserDefaultValidator(ClassDefine nowClassDefine, String validateRule, List<IFieldValidator> validators, String fileName, String sheetName, int i, int nowRow) {
        if(!validateRule.startsWith(Constant.ValidateMark.MARK_DefaultStart)){
            return;
        }
        String tempValue = validateRule.substring(Constant.ValidateMark.MARK_DefaultStart.length(),validateRule.length()-1);
        //TODO 根据tag的具体类型分析下这个类型下是否可以赋此默认值
//        DefaultValidatorI validator = new DefaultValidatorI();
//        validator.value = tempValue;
//        validators.add(validator);
        return;
    }
    //枚举解析
    public static void parserEnumValidator(ClassDefine nowClassDefine, String validateRule, List<IFieldValidator> validators, String fileName, String sheetName, int i, int nowRow) {
        if(!validateRule.startsWith(Constant.ValidateMark.MARK_EnumStart)){//不是枚举
            return;
        }
        String tempValue = validateRule.substring(Constant.ValidateMark.MARK_EnumStart.length(),validateRule.length()-1);
        String[] split = tempValue.split(Constant.ValidateMark.MARK_Sharp);
        if(split.length != 2){
            log.error("枚举校验规则必须包含枚举类名和校验值的类型(name/value),文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
            return;
        }
        //枚举名要加入依赖项，检测依赖是否存在
        String enumName = split[0];
//        EnumDefine anEnum = ExportContext.enumManager.getEnum(ed -> ed.enumName.equals(enumName));
//        if(anEnum == null){
//            log.error("枚举校验规则中的枚举类不存在，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
//            return;
//        }
//        String validateType = split[1];
//        if(!validateType.equals(Constant.EnumValidateType.TYPE_Name)
//                && !validateType.equals(Constant.EnumValidateType.TYPE_Value)
//                && !validateType.equals(Constant.EnumValidateType.TYPE_Desc)){
//            log.error("枚举校验规则中的校验类型不正确，必须是(name/value/desc)，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
//            return;
//        }
//        nowClassDefine.dependsEnum.add(enumName);
//        EnumValidatorI validator = new EnumValidatorI();
//        validator.enumClassName = enumName;
//        validator.validateType  = validateType;
//        validators.add(validator);
    }

    //数据范围限制
    public static void parserRangeValidator(ClassDefine nowClassDefine, String validateRule, List<IFieldValidator> validators, String fileName, String sheetName, int i, int nowRow) {
        if(!validateRule.startsWith(Constant.ValidateMark.MARK_RangeStart)){
            return;
        }
        String limitStr = validateRule.substring(6, validateRule.length()-1);
        String[] split = limitStr.split(Constant.ValidateMark.MARK_IndexSeperator);
        if(split.length != 2){
            log.error("limit校验规则中的参数个数不正确，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
            return;
        }
        String minStr = split[0];
        String maxStr = split[1];

        if(minStr.equals(Constant.ValidateMark.MARK_Any)){
            minStr = Integer.MIN_VALUE+"";
        }
        if(maxStr.equals(Constant.ValidateMark.MARK_Any)){
            maxStr = Integer.MAX_VALUE+"";
        }
        if(!minStr.matches(Constant.CommonRegex.REGEX_Number)){
            log.error("limit校验规则中的最小值不是数字，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
            return;
        }
        if(!maxStr.matches(Constant.CommonRegex.REGEX_Number)){
            log.error("limit校验规则中的最大值不是数字，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
            return;
        }
        int min = Integer.parseInt(minStr);
        int max = Integer.parseInt(maxStr);
//        RangeValidatorI validator = new RangeValidatorI();
//        validator.minV = min;
//        validator.maxV = max;
//        validators.add(validator);
    }

    public static void parserIdValidator(ClassDefine nowClassDefine, String validateRule, List<IFieldValidator> validators, String fileName, String sheetName, int i, int nowRow) {
        if(!validateRule.startsWith(Constant.ValidateMark.MARK_TableStart)){
            return;
        }
        String tableName = validateRule.substring(2, validateRule.length()-1);
        if(tableName.isEmpty()){
            log.error("Id校验规则中表名不能为空，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
            return;
        }
        nowClassDefine.dependsTable.add(tableName);
//        IdValidatorI validator = new IdValidatorI();
//        validator.tableName = tableName;
//        validators.add(validator);
    }

    public static void parserListValidator(ClassDefine nowClassDefine, String validateRule, List<IFieldValidator> validators, String fileName, String sheetName, int i, int nowRow) {
        if(!validateRule.startsWith(Constant.ValidateMark.MARK_OneListStart)){
            return;
        }
        int endStr = validateRule.indexOf(Constant.ValidateMark.MARK_OneListEnd);
        if(endStr == -1){
            log.error("List校验规则不正确，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
            return;
        }
        String itemIndexStr = validateRule.substring(1, endStr);
        Set<Integer> index = new HashSet<>();
        if(itemIndexStr.equals("?")){
            //do nothing
        }else if(itemIndexStr.contains(Constant.ValidateMark.MARK_And)){
            String[] split = itemIndexStr.split(Constant.ValidateMark.MARK_And);
            for (String s : split) {
                if(s.contains(Constant.ValidateMark.MARK_IndexRange)){
                    if(!addRangeIndex(s,index,fileName,sheetName,i,nowRow)){
                        return;
                    }
                }else{
                    boolean matches = s.trim().matches(Constant.CommonRegex.REGEX_Number);
                    if(matches){
                        index.add(Integer.valueOf(s));
                    }else {
                        log.error("一维List校验规则元素索引不正确，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
                        return;
                    }
                }
            }
            if(split.length==0){
                log.error("List校验规则未检测到元素索引，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
                return;
            }
        }else{
            boolean matches = itemIndexStr.trim().matches(Constant.CommonRegex.REGEX_Number);
            if(matches){
                index.add(Integer.valueOf(itemIndexStr));
            }else{
                log.error("List校验规则未检测到元素索引，文件名名："+fileName+" sheet名："+sheetName+" 行号："+nowRow+" 列："+i+" 校验字符串："+validateRule);
                return;
            }
        }

        String validateStr = validateRule.substring(endStr + 1);
        List<IFieldValidator> result = new ArrayList<>();
        parserValidateRule(true, nowClassDefine, validateStr,result,fileName,sheetName,i,nowRow);
        if(result.isEmpty()){
            return;
        }
//        ListValidatorI validator = new ListValidatorI() ;
//        validator.indexs.addAll(index);
//        validator.validator = result.get(0);
//        validators.add(validator);
    }
}
